package com.javaweb.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * @desc: 用于记录Dao层select方法的日志切面类。
 * 主要对Dao层的所有select方法进行日志记录，并记录其执行时间。
 */
@Aspect
@Component
@Slf4j
public class LogAspect {

    /**
     * 切入点：匹配Dao层所有以select开头的方法。
     * 匹配com.javaweb.dao包及其子包中所有以select开头的方法。
     */
    @Pointcut("execution(* com.javaweb.dao..*.select*(..))")
    public void daoLayerSelectMethods() {} // 定义一个切入点

    /**
     * 环绕通知：记录Dao层select方法的执行日志，并测量其执行时间。
     * 日志需要包括方法名称和执行时间。
     */
    @Around("daoLayerSelectMethods()")
    public Object logAndMeasureSelectMethods(ProceedingJoinPoint pjp) throws Throwable {
        // 获取当前方法的名称
        String methodName = pjp.getSignature().getName();

        // 记录方法开始执行的日志
        log.info("方法: {} 开始执行.", methodName);

        // 记录开始时间
        long startTime = System.currentTimeMillis();

        Object returnValue;
        try {
            // 执行目标方法
            returnValue = pjp.proceed();
        } catch (Throwable throwable) {
            // 如果方法抛出异常，记录错误日志
            log.error("方法: {} 执行时发生异常: {}", methodName, throwable.getMessage());
            throw throwable; // 重新抛出异常以确保正常流程
        }

        // 记录结束时间
        long endTime = System.currentTimeMillis();
        // 计算执行时间
        long executionTime = endTime - startTime;

        // 记录方法执行完毕的日志及其执行时间
        log.info("方法: {} 执行完毕，耗时: {} 毫秒.", methodName, executionTime);

        // 返回目标方法的返回值
        return returnValue;
    }

    @Around("@within(com.javaweb.aop.NPECatch) || @annotation(com.javaweb.aop.NPECatch)")
    public Object handleNPECatchException(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取当前方法名


        // 输出异常信息
        try {
            String methodName = joinPoint.getSignature().getName();
            return joinPoint.proceed();
        } catch (Throwable t) {
            log.error("Unexpected exception: {}", t.getMessage());

        }
        return null;

    }
}
